﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using CodeWriterHelper.Objects;
using System.Windows.Input;
using CodeWriterHelper.Commands;
using System.Xml.Serialization;
using System.IO;

namespace CodeWriterHelper.ViewModel
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<WriterOptions> _options = null;
        public ObservableCollection<WriterOptions> Options
        {
            get
            {
                if (_options == null)
                {
                    _options = new ObservableCollection<WriterOptions>();
                    _options.Add(CreateDefaultWriterOptions());
                }

                return _options;
            }
            set
            {
                _options = value;

                foreach (WriterOptions option in Options)
                {
                    RegisterToOptionsEvents(option);
                }

                RaisePropertyChanged("Options");
            }
        }

        public MainWindowViewModel()
        {
            LoadOptions();
        }

        private ICommand _addConfigCommand = null;
        public ICommand AddConfigCommand
        {
            get
            {
                if (_addConfigCommand == null)
                {
                    _addConfigCommand = new DelegateCommand(arg => {

                        WriterOptions newOptions = new WriterOptions();
                        newOptions.PropertyChanged += new PropertyChangedEventHandler(result_PropertyChanged);
                        Options.Add(newOptions);
                    });
                }

                return _addConfigCommand;
            }
            private set
            {
                if (_addConfigCommand != value)
                {
                    _addConfigCommand = value;
                    this.RaisePropertyChanged("AddConfigCommand");
                }
            }
        }

        private void LoadOptions()
        {
            if (File.Exists(serializedConfigsFilename))
            {
                LoadConfigurations();
            }
        }

        private WriterOptions CreateDefaultWriterOptions()
        {
            WriterOptions result = new WriterOptions();
            result.AddTab = "c.addToken();";
            result.EmptyRow = "c.writeLine();";
            result.LinePrefix = "c.writeLine(\"";
            result.LineSuffix = "\");";
            result.RemoveTab = "c.removeToken();";
            result.UseTabTokens = true;
            result.ReplaceEntries = new ObservableCollection<CodeReplaceEntry>();
            result.ReplaceEntries.Add(new CodeReplaceEntry() { StringToReplace = @"\", NewString = @"\\" });
            result.ReplaceEntries.Add(new CodeReplaceEntry() { StringToReplace = "\"", NewString = "\\\"" });
            RegisterToOptionsEvents(result);

            return result;
        }

        void result_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "ResultText")
            {
                ((WriterOptions)sender).buildTransformerCode();

                if (e.PropertyName != "OriginalText")
                {
                    SaveConfigurations();
                }
            }
        }

        private string serializedConfigsFilename = @"configs.xml";
        private object lockSave = new object();

        private void SaveConfigurations()
        {
            lock (lockSave)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<WriterOptions>));
                TextWriter textWriter = new StreamWriter(serializedConfigsFilename);
                serializer.Serialize(textWriter, Options);
                textWriter.Close();
            }
        }

        private void LoadConfigurations()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<WriterOptions>));
            Options = (ObservableCollection<WriterOptions>)serializer.Deserialize(File.Open(serializedConfigsFilename, FileMode.Open));
        }

        public void RegisterToOptionsEvents(WriterOptions options)
        {
            options.PropertyChanged += new PropertyChangedEventHandler(result_PropertyChanged);
            options.RemoveRequest += new EventHandler(options_RemoveRequest);
        }

        void options_RemoveRequest(object sender, EventArgs e)
        {
            WriterOptions optionsToRemove = (WriterOptions)sender;
            optionsToRemove.PropertyChanged -= result_PropertyChanged;
            optionsToRemove.RemoveRequest -= options_RemoveRequest;
            Options.Remove(optionsToRemove);

            if (Options.Count == 0)
            {
                Options = null;
            }
        }

        #region PropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion PropertyChanged
    }
}
